﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FileBrowserController.cs" company="ecblog.codeplex.com">
//   emrecoskun.net - ibrahimatay.com
// </copyright>
// <summary>
//   File browser control
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace EcBlog.Areas.Admin.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;

    using EcBlog.Admin.Models;
    using EcBlog.Models;

    using Telerik.Web.Mvc.UI;

    /// <summary>
    /// File browser control
    /// </summary>
    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
#if !(DEBUG)
    [Filters.Authorize(PortalRole.Admin)]
#endif
    public class FileBrowserController : Controller
    {
        #region ctor
        /// <summary>
        /// Gets the index view
        /// </summary>
        /// <returns>The index view </returns>
        public ActionResult Index()
        {
            var baseDirectory = this.Server.MapPath("/");
            var viewModel = GetServerFiles(baseDirectory);

            return this.View(viewModel);
        } 
        #endregion

        #region Core Action Methods
        /// <summary>
        /// Gets the node content.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns>The node content</returns>
        [HttpPost]
        public ActionResult AjaxLoading(TreeViewItem node)
        {
            var fullpath = node.Value;
            var viewModel = GetServerFiles(fullpath);

            return new JsonResult
                {
                    Data =
                        viewModel.Select(
                            c =>
                            new TreeViewItem
                                {
                                    Text = c.Name,
                                    Value = c.FullPath,
                                    LoadOnDemand = c.IsDirectory,
                                    Enabled = true,
                                    ImageUrl =
                                        c.IsDirectory
                                            ? this.Url.Content("~/Content/images/directory.png")
                                            : this.Url.Content("~/Content/images/" + c.Name.Substring(c.Name.LastIndexOf(".", StringComparison.Ordinal) + 1, c.Name.Length - 1 - c.Name.LastIndexOf(".", StringComparison.Ordinal)) + ".png")
                                })
                };
        }

        /// <summary>
        /// Deletes the specified file browser checked nodes.
        /// </summary>
        /// <param name="fileBrowserCheckedNodes">The file browser checked nodes.</param>
        /// <returns>The index view.</returns>
        [HttpPost]
        public ActionResult Delete(List<TreeViewItem> fileBrowserCheckedNodes)
        {
            var message = string.Empty;
            if (fileBrowserCheckedNodes != null)
            {
                foreach (var node in fileBrowserCheckedNodes)
                {
                    message += node.Text + "<br/>";
                    if (node.LoadOnDemand)
                    {
                        Directory.Delete(node.Value);
                    }
                    else
                    {
                        System.IO.File.Delete(node.Value);
                    }
                }
            }

            this.ViewData["message"] = message;
            this.ViewData["FileBrowser_checkedNodes"] = fileBrowserCheckedNodes;
            return this.RedirectToAction("Index");
        }

        /// <summary>
        /// Edits the specified selected path.
        /// </summary>
        /// <param name="selectedPath">The selected path.</param>
        /// <returns>The index view</returns>
        public ActionResult Edit(string selectedPath)
        {
            try
            {
                if (!string.IsNullOrEmpty(selectedPath))
                {
                    return this.View(new EditContentViewModel { Content = System.IO.File.ReadAllText(selectedPath) });
                }
            }
            catch (Exception e)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(e);
            }

            this.ViewData["message"] = "File not found!";
            return this.RedirectToAction("Index");
        }

        /// <summary>
        /// Edits the specified selected path.
        /// </summary>
        /// <param name="selectedPath">The selected path.</param>
        /// <param name="viewModel">The view model.</param>
        /// <returns>the index view.</returns>
        [HttpPost, ValidateInput(false)]
        public ActionResult Edit(string selectedPath, EditContentViewModel viewModel)
        {
            if (!string.IsNullOrEmpty(selectedPath))
            {
                System.IO.File.WriteAllText(selectedPath, viewModel.Content, Encoding.UTF8);
                return this.RedirectToAction("Index");
            }

            return this.RedirectToAction("Edit", new { selectedPath });
        }

        /// <summary>
        /// Processes the submit.
        /// </summary>
        /// <param name="attachments">The attachments.</param>
        /// <param name="selectedPath">The selected path.</param>
        /// <returns>The index view.</returns>
        [HttpPost]
        public ActionResult ProcessSubmit(IEnumerable<HttpPostedFileBase> attachments, string selectedPath)
        {
            if (attachments != null)
            {
                var list = attachments.ToList();
                this.TempData["UploadedAttachments"] = GetFileInfo(list);
                foreach (var attachment in list)
                {
                    var filename = Path.GetFileName(attachment.FileName);
                    if (filename == null)
                    {
                        continue;
                    }

                    var path = Path.Combine(selectedPath, filename);
                    if (System.IO.File.Exists(path))
                    {
                        System.IO.File.Delete(path);
                    }

                    attachment.SaveAs(path);
                }
            }

            return this.RedirectToAction("Index");
        } 
        #endregion

        #region Support Methods
        private static IEnumerable<string> GetFileInfo(IEnumerable<HttpPostedFileBase> attachments)
        {
            return
                from a in attachments
                where a != null
                select string.Format("{0} ({1} bytes)", Path.GetFileName(a.FileName), a.ContentLength);
        }

        private static IEnumerable<ServerFile> GetServerFiles(string baseDirectory)
        {
            var directories = Directory.GetDirectories(baseDirectory);
            var files = Directory.GetFiles(baseDirectory);
            return directories.Select(
                c =>
                new ServerFile
                    {
                        IsDirectory = true,
                        Name = c.Replace(baseDirectory, string.Empty).Replace(@"\", string.Empty),
                        FullPath = Path.Combine(baseDirectory, c)
                    }).ToList().Union(
                        files.Select(
                        c =>
                        new ServerFile
                            {
                                IsDirectory = false,
                                Name = c.Replace(baseDirectory, string.Empty).Replace(@"\", string.Empty),
                                FullPath = Path.Combine(baseDirectory, c)
                            }));
        } 
        #endregion
    }
}
